Python 高级3

四舍五入

1
2
3
4
print(round(1.5, 1))  # 1.5
print(round(1.23, 1)) # 1.2
print(round(-1.27, 1)) # -1.3
print(round(-1.25361, 3)) # -1.254

传给 round() 函数的 ndigits 参数可以是负数,这种情况下, 舍入运算会作用在十位、百位、千位等上面。比如

1
2
3
4
print(round(1627731, -1))  # 1627730
print(round(1627731, -2)) # 1627700
print(round(1627731, -3)) # 1628000
print(round(1627731, -4)) # 1630000

不要将舍入和格式化输出搞混淆了。 如果你的目的只是简单的输出一定宽度的数,你不需要使用 round() 函数。 而仅仅只需要在格式化的时候指定精度即可。比如:

1
2
3
4
# 格式化的时候指定精度,并非舍入
print(format(1.23456, '0.2f')) # 1.23
print(format(1.23456, '0.3f')) # 1.235
print(format(1.23456, '0.4f')) # 1.2346

精确的浮点数运算

浮点数的一个普遍问题是它们并不能精确的表示十进制数

1
2
3
4
5
6
7
>>> a = 4.2
>>> b = 2.1
>>> a + b
6.300000000000001
>>> (a + b) == 6.3
False
>>>

使用 decimal 解决问题,并且 decimal 模块中的 localcontext 还可以设置保留小数位数。计算效率上,原生的浮点数计算要快的多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from decimal import Decimal, localcontext

d1 = Decimal("4.2")
d2 = Decimal("2.1")
print(d1 + d2) # 6.3

# Decimal 可以自定义设置
d3 = Decimal("0.3")
d4 = Decimal("0.7")
print(d3/d4) # 0.4285714285714285714285714286

with localcontext() as ltx:
ltx.prec = 3 # 设置保留三位小数
print(d3 / d4) # 0.429

print(round(d3 / d4, 3)) # 0.429,使用 round 保留三位小数

进制转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
x = 1234

# 二进制
print(bin(x)) # 0b10011010010
# 八进制
print(oct(x)) # 0o2322
# 十六进制
print(hex(x)) # 0x4d2

# 无前缀显示二进制格式
print(format(x, "b")) # 10011010010

# 无前缀显示八进制格式
print(format(x, "o")) # 2322

# 无前缀显示十六进制格式
print(format(x, "x")) # 4d2

无穷大与NaN

1
2
3
4
5
6
7
8
9
print(float("inf"))  # inf, 正无穷
print(float("-inf")) # -inf, 负无穷
print(float('nan')) # nan, nan 代表 Not A Number(不是一个数),它并不等于0

import math

# 判断是否是无穷或者 nan
print(math.isinf(float("-inf"))) # True
print(math.isnan(float('nan'))) # True

分数

1
2
3
4
5
6
7
8
9
10
11
12
from fractions import Fraction

f1 = Fraction(5, 4) # 创建一个分数,5/4
f2 = Fraction(7, 16) # 创建一个分数,7/16

# 两个分数之间的计算
print(f1 + f2) # 27/16
print(f1 * f1) # 25/16

# 计算结果转为小数
print(float(f1 + f2)) # 1.6875
print(float(f1 * f2)) # 0.546875

随机数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import random

values = [1, 2, 3, 4, 5, 6]

# 随机选择一个数据
print(random.choices(values))

# 随机取出 3 个不同元素
print(random.sample(values, 3))

# 打乱元素的顺序
random.shuffle(values)
print(values)

# 生成随机整数
print(random.randint(0, 10))

# 生成0到1范围内均匀分布的浮点数
print(random.random())

字符串与日期的转换

String 转 DateTime

1
2
3
In [16]: time_str = '2018-02-28 14:00:00'
In [18]: datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
Out[18]: datetime.datetime(2018, 2, 28, 14, 0)

DateTime 转 String

1
2
3
In [19]: date_time = datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
In [20]: date_time.strftime("%Y-%m-%d %H:%M:%S")
Out[20]: '2018-02-28 14:00:00'

strptime() 的性能要比你想象中的差很多,如果知道时间字符串的格式,例如 YYYY-MM-DD ,那么可以像下面这样实现一个解析函数。

1
2
3
4
from datetime import datetime
def parse_ymd(s):
year_s, mon_s, day_s = s.split('-')
return datetime(int(year_s), int(mon_s), int(day_s))